package cn.lili.modules.wallet.handler;

import cn.lili.common.enums.ResultCode;
import cn.lili.common.exception.ServiceException;
import cn.lili.common.security.context.UserContext;
import cn.lili.common.utils.DateUtil;
import cn.lili.modules.order.order.entity.enums.PayStatusEnum;
import cn.lili.modules.payment.entity.dos.Recharge;
import cn.lili.modules.payment.entity.dto.PayParam;
import cn.lili.modules.payment.entity.dto.PayParamItem;
import cn.lili.modules.payment.entity.dto.PaymentCallback;
import cn.lili.modules.payment.entity.enums.PaymentClientEnum;
import cn.lili.modules.payment.entity.enums.PaymentMethodEnum;
import cn.lili.modules.payment.entity.enums.PaymentSceneEnums;
import cn.lili.modules.payment.entity.enums.PlatformWalletEnum;
import cn.lili.modules.payment.entity.vo.RechargeCashierParamVO;
import cn.lili.modules.wallet.service.RechargeService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 交易收银台
 *
 * @author Chopper
 * @since 2021-01-25 20:00
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class RechargeCashier {

    private final RechargeService rechargeService;


    /**
     * 加工付款VO
     *
     * @param sn                     交易编号
     * @param rechargeCashierParamVO 订单收银台参数
     * @return 支付参数
     */
    public RechargeCashierParamVO handlerCashierParams(String sn, RechargeCashierParamVO rechargeCashierParamVO) {

        Recharge recharge = rechargeService.getRechargeBySn(sn);
        //交易有效性判定
        if (recharge == null || recharge.getPayStatus().equals(PayStatusEnum.PAID.name()) || recharge.getPayStatus().equals(PayStatusEnum.CANCEL.name())) {
            throw new ServiceException(ResultCode.PAY_NOT_EXIST_ORDER);
        }
        //订单信息获取
        rechargeCashierParamVO.setOrderSn(recharge.getRechargeSn());

        rechargeCashierParamVO.setPrice(recharge.getRechargeMoney());

        String subject = "在线支付";
        rechargeCashierParamVO.setDetail(subject);

        rechargeCashierParamVO.setCreateTime(recharge.getCreateTime());


        Date autoCancel = DateUtil.offsetMinute(recharge.getCreateTime(), getAutoCancelTime());

        if (autoCancel.before(new Date())) {
            rechargeCashierParamVO.setAutoCancel(autoCancel.getTime());
            rechargeService.cancel(sn);
            throw new ServiceException(ResultCode.ORDER_NOT_EXIST);
        }
        rechargeCashierParamVO.setAutoCancel(autoCancel.getTime());

        return rechargeCashierParamVO;
    }


    /**
     * 生成支付参数
     *
     * @param sn 交易编号
     * @return 支付参数
     */
    public PayParam generatePaymentParams(String sn, PaymentClientEnum paymentClientEnum, PaymentMethodEnum paymentMethodEnum) {

        Recharge recharge = rechargeService.getRechargeBySn(sn);
        //交易有效性判定
        if (recharge == null || recharge.getPayStatus().equals(PayStatusEnum.PAID.name())) {
            throw new ServiceException(ResultCode.PAY_NOT_EXIST_ORDER);
        }


        List<PayParamItem> payParamItems = new ArrayList<>();

        payParamItems.add(
                PayParamItem.builder()
                        .sn(sn)
                        .price(recharge.getRechargeMoney())
                        .payeeId(PlatformWalletEnum.BALANCE.getWalletUserId())
                        .description("在线充值")
                        .build()
        );

        return PayParam.builder()
                .combineSn(sn)
                .payerId(recharge.getUserId())
                .paymentClientEnum(paymentClientEnum)
                .paymentMethodEnum(paymentMethodEnum)
                .payParamItems(payParamItems)
                .paymentSceneEnums(PaymentSceneEnums.RECHARGE)
                .timeoutExpress(getAutoCancelTime())
                .build();
    }

    /**
     * 支付成功
     *
     * @param paymentCallback 支付回调
     */
    public void paymentCallback(PaymentCallback paymentCallback) {
        rechargeService.paySuccess(paymentCallback);
    }


    /**
     * 获取自动取消时间
     *
     * @return 自动取消时间
     */
    private Integer getAutoCancelTime() {
        return 30;
    }
}